/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2024-05-06     liuchao       the first version
 */
#include "configuration.h"
#define LOG_TAG "configuration"
#define LOG_LVL LOG_LVL_DBG
#include "ulog.h"

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define EEPROM_I2C_BUS_NAME "i2c1"
static at24cxx_device_t s_ee_dev = RT_NULL;
static rt_mutex_t s_mutex = NULL;

static char s_mqtt_host[256] = { 0 };
#define MQTT_HOST_OFFSET 0

static char s_mqtt_port[16] = "1883";
#define MQTT_PORT_OFFSET (sizeof(s_mqtt_host))

static char s_mqtt_client_id[256] = { 0 };
#define MQTT_CLIENT_ID_OFFSET (MQTT_PORT_OFFSET + sizeof(s_mqtt_port))

static char s_mqtt_user_name[256] = { 0 };
#define MQTT_USER_NAME_OFFSET (MQTT_CLIENT_ID_OFFSET + sizeof(s_mqtt_client_id))

static char s_mqtt_passwd[256] = { 0 };
#define MQTT_PASSWD_OFFSET (MQTT_USER_NAME_OFFSET + sizeof(s_mqtt_user_name))
// 油压
static char s_sensor_oil_pressure_baseline[4] = { 0 };
#define SENSOR_OIL_PRESSURE_BASELINE_OFFSET (MQTT_PASSWD_OFFSET + sizeof(s_mqtt_passwd))
// 油缸位移
static char s_sensor_putter_distance_baseline[4] = { 0 };
#define SENSOR_PUTTER_DISTANCE_BASELINE_OFFSET \
    (SENSOR_OIL_PRESSURE_BASELINE_OFFSET + sizeof(s_sensor_oil_pressure_baseline))
// 齿轮位移
static char s_sensor_gear_distance_baseline[4] = { 0 };
#define SENSOR_GEAR_DISTANCE_BASELINE_OFFSET \
    (SENSOR_PUTTER_DISTANCE_BASELINE_OFFSET + sizeof(s_sensor_putter_distance_baseline))
// 油温
static char s_sensor_oil_temp_baseline[4] = { 0 };
#define SENSOR_OIL_TEMP_BASELINE_OFFSET \
    (SENSOR_GEAR_DISTANCE_BASELINE_OFFSET + sizeof(s_sensor_gear_distance_baseline))
// 油量
static char s_sensor_oil_volume_baseline[4] = { 0 };
#define SENSOR_OIL_VOLUME_BASELINE_OFFSET \
    (SENSOR_OIL_TEMP_BASELINE_OFFSET + sizeof(s_sensor_oil_temp_baseline))
// 油压2
static char s_sensor_oil_pressure_2_baseline[4] = { 0 };
#define SENSOR_OIL_PRESSURE_2_BASELINE_OFFSET \
    (SENSOR_OIL_VOLUME_BASELINE_OFFSET + sizeof(s_sensor_oil_volume_baseline))
// 轴力系数K
static char s_axial_k[4] = { 0 };
#define AXIAL_K_OFFSET \
    (SENSOR_OIL_PRESSURE_2_BASELINE_OFFSET + sizeof(s_sensor_oil_pressure_2_baseline))
// 轴力系数b
static char s_axial_b[4] = { 0 };
#define AXIAL_B_OFFSET \
    (AXIAL_K_OFFSET + sizeof(s_axial_k))

static char s_mqtt_product_secret[128] = { 0 };
#define MQTT_PRODUCT_SECRET_OFFSET (AXIAL_B_OFFSET + sizeof(s_axial_b))

static char s_mqtt_device_secret[128] = { 0 };
#define MQTT_DEVICE_SECRET_OFFSET \
    (MQTT_PRODUCT_SECRET_OFFSET + sizeof(s_mqtt_product_secret))

static char s_putter_distance_min[4] = { 0 };
#define PUTTER_DISTANCE_MIN_OFFSET \
    (MQTT_DEVICE_SECRET_OFFSET + sizeof(s_mqtt_device_secret))

static char s_putter_distance_max[4] = { 0 };
#define PUTTER_DISTANCE_MAX_OFFSET \
    (PUTTER_DISTANCE_MIN_OFFSET + sizeof(s_putter_distance_min))

static char s_up_counts[4] = { 0 };
#define UP_COUNTS_OFFSET \
    (PUTTER_DISTANCE_MAX_OFFSET + sizeof(s_putter_distance_max))

static char s_run_seconds[4] = { 0 };
#define RUN_SECONDS_OFFSET \
    (UP_COUNTS_OFFSET + sizeof(s_up_counts))

static char s_hy_run_ms[4] = { 0 };
#define HY_RUN_MS_OFFSET \
    (RUN_SECONDS_OFFSET + sizeof(s_run_seconds))

const char* configuration_name(configuration_e configuration)
{
    switch (configuration)
    {
    case CONFIGURATION_MQTT_HOST:
        return "MQTT_HOST";
    case CONFIGURATION_MQTT_PORT:
        return "MQTT_PORT";
    case CONFIGURATION_MQTT_CLIENT_ID:
        return "MQTT_CLIENT_ID";
    case CONFIGURATION_MQTT_USER_NAME:
        return "MQTT_USER_NAME";
    case CONFIGURATION_MQTT_PASSWD:
        return "MQTT_PASSWD";
        // 油压
    case CONFIGURATION_SENSOR_OIL_PRESSURE_BASELINE:
        return "SENSOR_OIL_PERSSURE_BASELINE";
        // 油缸位移
    case CONFIGURATION_SENSOR_PUTTER_DISTANCE_BASELINE:
        return "SENSOR_PUTTER_DISTANCE_BASELINE";
        // 齿轮位移
    case CONFIGURATION_SENSOR_GEAR_DISTANCE_BASELINE:
        return "SENSOR_GEAR_DISTANCE_BASELINE";
        // 油温
    case CONFIGURATION_SENSOR_OIL_TEMP_BASELINE:
        return "SENSOR_OIL_TEMP_BASELINE";
        // 油量
    case CONFIGURATION_SENSOR_OIL_VOLUME_BASELINE:
        return "SENSOR_OIL_VOLUME_BASELINE";
        // 油压2
    case CONFIGURATION_SENSOR_OIL_PRESSURE_2_BASELINE:
        return "SENSOR_OIL_PRESSURE_2_BASELINE";
        // 轴力系数K
    case CONFIGURATION_AXIAL_K:
        return "AXIAL_K";
        // 轴力系数b
    case CONFIGURATION_AXIAL_B:
        return "AXIAL_B";
    case CONFIGURATION_MQTT_PRODUCT_SECRET:
        return "MQTT_PRODUCT_SECRET";
    case CONFIGURATION_MQTT_DEVICE_SECRET:
        return "MQTT_DEVICE_SECRET";
    case CONFIGURATION_PUTTER_DISTANCE_MAX:
        return "PUTTER_DISTANCE_MAX";
    case CONFIGURATION_PUTTER_DISTANCE_MIN:
        return "PUTTER_DISTANCE_MIN";
    case CONFIGURATION_UP_COUNTS:
        return "UP_COUNTS";
    case CONFIGURATION_RUN_SECONDS:
        return "RUN_SECONDS";
    case CONFIGURATION_HY_RUN_MS:
        return "HY_RUN_MS";
    default:
        return "UNKNOWN";
    }
}

configuration_type_e configuration_type(configuration_e configuration)
{
    switch (configuration)
    {
    // 油压
    case CONFIGURATION_SENSOR_OIL_PRESSURE_BASELINE:
        // 油缸位移
    case CONFIGURATION_SENSOR_PUTTER_DISTANCE_BASELINE:
        // 齿轮位移
    case CONFIGURATION_SENSOR_GEAR_DISTANCE_BASELINE:
        // 油温
    case CONFIGURATION_SENSOR_OIL_TEMP_BASELINE:
        // 油量
    case CONFIGURATION_SENSOR_OIL_VOLUME_BASELINE:
        // 油压2
    case CONFIGURATION_SENSOR_OIL_PRESSURE_2_BASELINE:
    case CONFIGURATION_UP_COUNTS:
    case CONFIGURATION_RUN_SECONDS:
    case CONFIGURATION_HY_RUN_MS:
        return CONFIGURATION_TYPE_UINT32;
        // 轴力系数K
    case CONFIGURATION_AXIAL_K:
        // 轴力系数b
    case CONFIGURATION_AXIAL_B:
    case CONFIGURATION_PUTTER_DISTANCE_MAX:
    case CONFIGURATION_PUTTER_DISTANCE_MIN:
        return CONFIGURATION_TYPE_FLOAT;
    default:
        return CONFIGURATION_TYPE_STR;
    }
}

static rt_uint32_t configuration_size(configuration_e configuration)
{
    rt_uint32_t ret = 0;
    switch (configuration)
    {
    case CONFIGURATION_MQTT_HOST:
        ret = sizeof(s_mqtt_host);
        break;
    case CONFIGURATION_MQTT_PORT:
        ret = sizeof(s_mqtt_port);
        break;
    case CONFIGURATION_MQTT_CLIENT_ID:
        ret = sizeof(s_mqtt_client_id);
        break;
    case CONFIGURATION_MQTT_USER_NAME:
        ret = sizeof(s_mqtt_user_name);
        break;
    case CONFIGURATION_MQTT_PASSWD:
        ret = sizeof(s_mqtt_passwd);
        break;
        // 油压
    case CONFIGURATION_SENSOR_OIL_PRESSURE_BASELINE:
        ret = sizeof(s_sensor_oil_pressure_baseline);
        break;
        // 油缸位移
    case CONFIGURATION_SENSOR_PUTTER_DISTANCE_BASELINE:
        ret = sizeof(s_sensor_putter_distance_baseline);
        break;
        // 齿轮位移
    case CONFIGURATION_SENSOR_GEAR_DISTANCE_BASELINE:
        ret = sizeof(s_sensor_gear_distance_baseline);
        break;
        // 油温
    case CONFIGURATION_SENSOR_OIL_TEMP_BASELINE:
        ret = sizeof(s_sensor_oil_temp_baseline);
        break;
        // 油量
    case CONFIGURATION_SENSOR_OIL_VOLUME_BASELINE:
        ret = sizeof(s_sensor_oil_volume_baseline);
        break;
        // 油压2
    case CONFIGURATION_SENSOR_OIL_PRESSURE_2_BASELINE:
        ret = sizeof(s_sensor_oil_pressure_2_baseline);
        break;
        // 轴力系数K
    case CONFIGURATION_AXIAL_K:
        ret = sizeof(s_axial_k);
        break;
        // 轴力系数b
    case CONFIGURATION_AXIAL_B:
        ret = sizeof(s_axial_b);
        break;
    case CONFIGURATION_MQTT_PRODUCT_SECRET:
        ret = sizeof(s_mqtt_product_secret);
        break;
    case CONFIGURATION_MQTT_DEVICE_SECRET:
        ret = sizeof(s_mqtt_device_secret);
        break;
    case CONFIGURATION_PUTTER_DISTANCE_MAX:
        ret = sizeof(s_putter_distance_max);
        break;
    case CONFIGURATION_PUTTER_DISTANCE_MIN:
        ret = sizeof(s_putter_distance_min);
        break;
    case CONFIGURATION_UP_COUNTS:
        ret = sizeof(s_up_counts);
        break;
    case CONFIGURATION_RUN_SECONDS:
        ret = sizeof(s_run_seconds);
        break;
    case CONFIGURATION_HY_RUN_MS:
        ret = sizeof(s_hy_run_ms);
        break;
    default:
        break;
    }
    return ret;
}

static char* configuration_addr(configuration_e configuration)
{
    char* ret = NULL;
    switch (configuration)
    {
    case CONFIGURATION_MQTT_HOST:
        ret = s_mqtt_host;
        break;
    case CONFIGURATION_MQTT_PORT:
        ret = s_mqtt_port;
        break;
    case CONFIGURATION_MQTT_CLIENT_ID:
        ret = s_mqtt_client_id;
        break;
    case CONFIGURATION_MQTT_USER_NAME:
        ret = s_mqtt_user_name;
        break;
    case CONFIGURATION_MQTT_PASSWD:
        ret = s_mqtt_passwd;
        break;
        // 油压
    case CONFIGURATION_SENSOR_OIL_PRESSURE_BASELINE:
        ret = s_sensor_oil_pressure_baseline;
        break;
        // 油缸位移
    case CONFIGURATION_SENSOR_PUTTER_DISTANCE_BASELINE:
        ret = s_sensor_putter_distance_baseline;
        break;
        // 齿轮位移
    case CONFIGURATION_SENSOR_GEAR_DISTANCE_BASELINE:
        ret = s_sensor_gear_distance_baseline;
        break;
        // 油温
    case CONFIGURATION_SENSOR_OIL_TEMP_BASELINE:
        ret = s_sensor_oil_temp_baseline;
        break;
        // 油量
    case CONFIGURATION_SENSOR_OIL_VOLUME_BASELINE:
        ret = s_sensor_oil_volume_baseline;
        break;
        // 油压2
    case CONFIGURATION_SENSOR_OIL_PRESSURE_2_BASELINE:
        ret = s_sensor_oil_pressure_2_baseline;
        break;
        // 轴力系数K
    case CONFIGURATION_AXIAL_K:
        ret = s_axial_k;
        break;
        // 轴力系数b
    case CONFIGURATION_AXIAL_B:
        ret = s_axial_b;
        break;
    case CONFIGURATION_MQTT_PRODUCT_SECRET:
        ret = s_mqtt_product_secret;
        break;
    case CONFIGURATION_MQTT_DEVICE_SECRET:
        ret = s_mqtt_device_secret;
        break;
    case CONFIGURATION_PUTTER_DISTANCE_MAX:
        ret = s_putter_distance_max;
        break;
    case CONFIGURATION_PUTTER_DISTANCE_MIN:
        ret = s_putter_distance_min;
        break;
    case CONFIGURATION_UP_COUNTS:
        ret = s_up_counts;
        break;
    case CONFIGURATION_RUN_SECONDS:
        ret = s_run_seconds;
        break;
    case CONFIGURATION_HY_RUN_MS:
        ret = s_hy_run_ms;
        break;
    default:
        break;
    }

    return ret;
}

static rt_uint32_t configuration_offset(configuration_e configuration)
{
    rt_uint32_t ret = RT_UINT32_MAX;

    switch (configuration)
    {
    case CONFIGURATION_MQTT_HOST:
        ret = MQTT_HOST_OFFSET;
        break;
    case CONFIGURATION_MQTT_PORT:
        ret = MQTT_PORT_OFFSET;
        break;
    case CONFIGURATION_MQTT_CLIENT_ID:
        ret = MQTT_CLIENT_ID_OFFSET;
        break;
    case CONFIGURATION_MQTT_USER_NAME:
        ret = MQTT_USER_NAME_OFFSET;
        break;
    case CONFIGURATION_MQTT_PASSWD:
        ret = MQTT_PASSWD_OFFSET;
        break;
        // 油压
    case CONFIGURATION_SENSOR_OIL_PRESSURE_BASELINE:
        ret = SENSOR_OIL_PRESSURE_BASELINE_OFFSET;
        break;
        // 油缸位移
    case CONFIGURATION_SENSOR_PUTTER_DISTANCE_BASELINE:
        ret = SENSOR_PUTTER_DISTANCE_BASELINE_OFFSET;
        break;
        // 齿轮位移
    case CONFIGURATION_SENSOR_GEAR_DISTANCE_BASELINE:
        ret = SENSOR_GEAR_DISTANCE_BASELINE_OFFSET;
        break;
        // 油温
    case CONFIGURATION_SENSOR_OIL_TEMP_BASELINE:
        ret = SENSOR_OIL_TEMP_BASELINE_OFFSET;
        break;
        // 油量
    case CONFIGURATION_SENSOR_OIL_VOLUME_BASELINE:
        ret = SENSOR_OIL_VOLUME_BASELINE_OFFSET;
        break;
        // 油压2
    case CONFIGURATION_SENSOR_OIL_PRESSURE_2_BASELINE:
        ret = SENSOR_OIL_PRESSURE_2_BASELINE_OFFSET;
        break;
        // 轴力系数K
    case CONFIGURATION_AXIAL_K:
        ret = AXIAL_K_OFFSET;
        break;
        // 轴力系数b
    case CONFIGURATION_AXIAL_B:
        ret = AXIAL_B_OFFSET;
        break;
    case CONFIGURATION_MQTT_PRODUCT_SECRET:
        ret = MQTT_PRODUCT_SECRET_OFFSET;
        break;
    case CONFIGURATION_MQTT_DEVICE_SECRET:
        ret = MQTT_DEVICE_SECRET_OFFSET;
        break;
    case CONFIGURATION_PUTTER_DISTANCE_MAX:
        ret = PUTTER_DISTANCE_MAX_OFFSET;
        break;
    case CONFIGURATION_PUTTER_DISTANCE_MIN:
        ret = PUTTER_DISTANCE_MIN_OFFSET;
        break;
    case CONFIGURATION_UP_COUNTS:
        ret = UP_COUNTS_OFFSET;
        break;
    case CONFIGURATION_RUN_SECONDS:
        ret = RUN_SECONDS_OFFSET;
        break;
    case CONFIGURATION_HY_RUN_MS:
        ret = HY_RUN_MS_OFFSET;
        break;
    default:
        break;
    }

    return ret;
}

char* configuration_get(configuration_e configuration)
{
    if (configuration < CONFIGURATION_START || configuration >= CONFIGRATION_END)
    {
        LOG_E("Invalid configuration get: %d", configuration);
        return NULL;
    }
    char* ret = NULL;
    rt_mutex_take(s_mutex, RT_WAITING_FOREVER);
    rt_uint32_t offset = configuration_offset(configuration);
    rt_uint32_t size = configuration_size(configuration);
    ret = configuration_addr(configuration);
    configuration_type_e type = configuration_type(configuration);

    if (offset != RT_UINT32_MAX && size != 0 && ret)
    {
        rt_uint32_t reset_size = 0;
        for (int i = 0; i < size; i++)
        {
            if (ret[i] == 0xff)
            {
                reset_size += 1;
            }
        }
        if (reset_size == size)
        {
            LOG_D("configuration get %d", configuration);
            if (at24cxx_read(s_ee_dev, offset, (uint8_t *) ret, size) != RT_EOK)
            {
                ret = NULL;
            }
            else
            {
                if (type == CONFIGURATION_TYPE_UINT32)
                {
                    LOG_D("get %x %x %x %x", ret[0], ret[1], ret[2], ret[3]);
                }
            }
        }
    }
    rt_mutex_release(s_mutex);
    return ret;
}
rt_err_t configuration_set(configuration_e configuration, const char* value)
{
    if (configuration < CONFIGURATION_START || configuration >= CONFIGRATION_END)
    {
        LOG_E("Invalid configuration set: %d", configuration);
        return RT_ERROR;
    }
    rt_err_t ret = RT_EOK;

    rt_uint32_t offset = configuration_offset(configuration);
    rt_uint32_t size = configuration_size(configuration);
    char* addr = configuration_addr(configuration);
    configuration_type_e type = configuration_type(configuration);

    rt_mutex_take(s_mutex, RT_WAITING_FOREVER);
    if (offset != RT_UINT32_MAX && size != 0 && addr)
    {
        LOG_D("configuration set %d", configuration);
        if (type == CONFIGURATION_TYPE_UINT32)
        {
            LOG_D("set %x %x %x %x", value[0], value[1], value[2], value[3]);
        }
        memcpy(addr, value, size);
        ret = at24cxx_write(s_ee_dev, offset, (uint8_t*) addr, size);
        memset(addr, 0xff, size);
    }
    rt_mutex_release(s_mutex);

    return ret;
}

rt_uint32_t configuration_get_uint32(configuration_e configuration)
{
    rt_uint32_t ret = RT_UINT32_MAX;
    const char* raw = configuration_get(configuration);
    ret = *(rt_uint32_t*) raw;
    return ret;
}
rt_err_t configuration_set_uint32(configuration_e configuration, rt_uint32_t value)
{
    const char* raw = (char*) &value;
    return configuration_set(configuration, raw);
}

float configuration_get_float(configuration_e configuration)
{
    float ret = 0.0;
    const char* raw = configuration_get(configuration);
    ret = *(float*) raw;
    return ret;
}
rt_err_t configuration_set_float(configuration_e configuration, float value)
{
    const char* raw = (char*) &value;
    return configuration_set(configuration, raw);
}

int configuration_is_mqtt_host_valid()
{
    const char* host = configuration_get(CONFIGURATION_MQTT_HOST);
    if (host[0] == 0xff || host[1] == 0xff || host[2] == 0xff)
    {
        // LOG_E("mqtt host seems not right, set mqtt parameters, then reboot");
        return 0;
    }
    return 1;
}

float configuration_putter_distance_min()
{
    float v = configuration_get_float(CONFIGURATION_PUTTER_DISTANCE_MIN);
    if (isnan(v))
    {
        return 0.0;
    }
    return v;
}
float configuration_putter_distance_max()
{
    float v = configuration_get_float(CONFIGURATION_PUTTER_DISTANCE_MAX);
    if (isnan(v))
    {
        return 200.0;
    }
    return v;
}

void configuration_dump()
{
    for (configuration_e i = CONFIGURATION_START; i < CONFIGRATION_END; i++)
    {
        configuration_type_e t = configuration_type(i);
        const char* name = configuration_name(i);
        switch (t)
        {
        case CONFIGURATION_TYPE_STR:
            rt_kprintf("%s: %s\n", name, configuration_get(i));
            break;
        case CONFIGURATION_TYPE_UINT32:
            rt_kprintf("%s: %lu\n", name, configuration_get_uint32(i));
            break;
        case CONFIGURATION_TYPE_FLOAT:
            rt_kprintf("%s: %f\n", name, configuration_get_float(i));
            break;
        default:
            rt_kprintf("%s: UNKNOWN", name);
            break;
        }
    }
}

void configuration_reset_counter()
{
    configuration_set_uint32(CONFIGURATION_UP_COUNTS, 0);
    configuration_set_uint32(CONFIGURATION_RUN_SECONDS, 0);
    configuration_set_uint32(CONFIGURATION_HY_RUN_MS, 0);
}

static float s_auto_mode_baseline = 0;
static float s_auto_mode_percentage = 0;
static rt_int32_t s_auto_mode_update_interval = -1;
static rt_int32_t s_auto_mode_update_delay = -1;
static rt_int32_t s_rotate_handled = 0;
static rt_mutex_t s_v_mutex = NULL;
float auto_mode_baseline()
{
    float ret = 0;
    rt_mutex_take(s_v_mutex, RT_WAITING_FOREVER);
    ret = s_auto_mode_baseline;
    rt_mutex_release(s_v_mutex);
    return ret;
}
rt_err_t auto_mode_set_baseline(float v)
{
    rt_mutex_take(s_v_mutex, RT_WAITING_FOREVER);
    s_auto_mode_baseline = v;
    rt_mutex_release(s_v_mutex);
    return RT_EOK;
}
float auto_mode_percentage()
{
    float ret = 0;
    rt_mutex_take(s_v_mutex, RT_WAITING_FOREVER);
    ret = s_auto_mode_percentage;
    rt_mutex_release(s_v_mutex);
    return ret;
}
rt_err_t auto_mode_set_percentage(float v)
{
    v /= 100.0;
    rt_mutex_take(s_v_mutex, RT_WAITING_FOREVER);
    s_auto_mode_percentage = v;
    rt_mutex_release(s_v_mutex);
    return RT_EOK;
}

rt_int32_t auto_mode_update_inverval()
{
    rt_int32_t ret = 0;
    rt_mutex_take(s_v_mutex, RT_WAITING_FOREVER);
    ret = s_auto_mode_update_interval;
    rt_mutex_release(s_v_mutex);
    return ret;
}
rt_err_t auto_mode_set_update_interval(rt_int32_t v)
{
#if 0
    if (v > 0 && v < 60)
    {
        v = 60;
    }
#endif
    rt_mutex_take(s_v_mutex, RT_WAITING_FOREVER);
    s_auto_mode_update_interval = v;
    rt_mutex_release(s_v_mutex);
    return RT_EOK;
}
rt_int32_t auto_mode_update_delay()
{
    rt_int32_t ret = 0;
    rt_mutex_take(s_v_mutex, RT_WAITING_FOREVER);
    ret = s_auto_mode_update_delay;
    rt_mutex_release(s_v_mutex);
    return ret;
}
rt_err_t auto_mode_set_update_delay(rt_int32_t v)
{
    if (v < 0)
    {
        return RT_ERROR;
    }
    rt_mutex_take(s_v_mutex, RT_WAITING_FOREVER);
    s_auto_mode_update_delay = v;
    rt_mutex_release(s_v_mutex);
    return RT_EOK;
}
rt_int32_t rotate_handled()
{
    rt_int32_t ret = 0;
    rt_mutex_take(s_v_mutex, RT_WAITING_FOREVER);
    ret = s_rotate_handled;
    rt_mutex_release(s_v_mutex);
    return ret;
}
rt_err_t rotate_set_handled(rt_int32_t v)
{
    rt_mutex_take(s_v_mutex, RT_WAITING_FOREVER);
    s_rotate_handled = v;
    rt_mutex_release(s_v_mutex);
    return RT_EOK;
}
#include <time.h>
static rt_int32_t s_axial_is_met = 0;
static time_t s_axial_met_ts = 0;
rt_int32_t axial_is_met()
{
    rt_int32_t ret = 0;
    rt_mutex_take(s_v_mutex, RT_WAITING_FOREVER);
    ret = s_axial_is_met;
    rt_mutex_release(s_v_mutex);
    return ret;
}
rt_err_t axial_set_is_met(rt_int32_t v)
{
    rt_mutex_take(s_v_mutex, RT_WAITING_FOREVER);
    s_axial_is_met = v;
    if (v)
    {
        s_axial_met_ts = time(NULL);
    }
    rt_mutex_release(s_v_mutex);
    return RT_EOK;
}
time_t axial_met_ts()
{
    time_t ret = 0;
    rt_mutex_take(s_v_mutex, RT_WAITING_FOREVER);
    ret = s_axial_met_ts;
    rt_mutex_release(s_v_mutex);
    return ret;
}

rt_uint32_t up_counts()
{
    rt_uint32_t ret = configuration_get_uint32(CONFIGURATION_UP_COUNTS);
    if (ret == RT_UINT32_MAX)
    {
        ret = 1;
        configuration_set_uint32(CONFIGURATION_UP_COUNTS, 1);
    }
    return ret;
}

rt_uint32_t up_counts_inc()
{
    rt_uint32_t cur_up_counts = up_counts();
    cur_up_counts++;
    configuration_set_uint32(CONFIGURATION_UP_COUNTS, cur_up_counts);
    return cur_up_counts;
}

rt_uint32_t sleep_seconds_get()
{
    rt_uint32_t ret = configuration_get_uint32(CONFIGURATION_RUN_SECONDS);
    LOG_D("sleep sencods: %lu", ret);
    if (ret == RT_UINT32_MAX)
    {
        ret = 0;
        configuration_set_uint32(CONFIGURATION_RUN_SECONDS, 0);
    }
    return ret;
}
rt_err_t sleep_seconds_set(rt_uint32_t v)
{
    LOG_D("sleep sencods set: %lu", v);
    rt_err_t ret = configuration_set_uint32(CONFIGURATION_RUN_SECONDS, v);
    if (ret != RT_EOK)
    {
        LOG_E("sleep sencods set: %lu failed", v);
    }
    return ret;
}

static int s_go_back_seconds = 0;
void go_back_seconds_set(int seconds)
{
    rt_mutex_take(s_v_mutex, RT_WAITING_FOREVER);
    s_go_back_seconds = seconds;
    rt_mutex_release(s_v_mutex);
}
int go_back_seconds_get()
{
    int ret = 0;
    rt_mutex_take(s_v_mutex, RT_WAITING_FOREVER);
    ret = s_go_back_seconds;
    rt_mutex_release(s_v_mutex);
    return ret;
}

static int s_pause_switch = 0;      //暂停状态
void pause_switch_set(int state)
{
    rt_mutex_take(s_v_mutex, RT_WAITING_FOREVER);
    s_pause_switch = state;
    rt_mutex_release(s_v_mutex);
}
int pause_switch_get()
{
    int ret = 0;
    rt_mutex_take(s_v_mutex, RT_WAITING_FOREVER);
    ret = s_pause_switch;
    rt_mutex_release(s_v_mutex);
    return ret;
}
static float s_bat_low_thd = -1;
void battery_low_threshold_set(float v)
{
    rt_mutex_take(s_v_mutex, RT_WAITING_FOREVER);
    s_bat_low_thd = v;
    rt_mutex_release(s_v_mutex);
}
float battery_low_threshold_get()
{
    float ret = 0;
    rt_mutex_take(s_v_mutex, RT_WAITING_FOREVER);
    ret = s_bat_low_thd;
    rt_mutex_release(s_v_mutex);
    return ret;
}

static int s_release_pressure_seconds = 0;
void release_pressure_set(int value)
{
    if (value > 30)
    {
        LOG_W("release pressure set too big: %d", value);
        return;
    }
    rt_mutex_take(s_v_mutex, RT_WAITING_FOREVER);
    s_release_pressure_seconds = value;
    rt_mutex_release(s_v_mutex);
}
int release_pressure_get()
{
    int ret = 0;
    rt_mutex_take(s_v_mutex, RT_WAITING_FOREVER);
    ret = s_release_pressure_seconds;
    rt_mutex_release(s_v_mutex);
    return ret;
}

static int init_eeprom()
{
    ulog_tag_lvl_filter_set(LOG_TAG, LOG_LVL_INFO);
    for (int configuration = CONFIGURATION_START; configuration < CONFIGRATION_END; configuration++)
    {
        rt_uint32_t size = configuration_size(configuration);
        char *addr = configuration_addr(configuration);
        memset(addr, 0xff, size);
    }
    s_v_mutex = rt_mutex_create("rot_v", RT_IPC_FLAG_PRIO);
    s_ee_dev = at24cxx_init(EEPROM_I2C_BUS_NAME, 0);
    s_mutex = rt_mutex_create("configuration", RT_IPC_FLAG_PRIO);

    up_counts_inc();
    configuration_dump();
    return RT_EOK;
}
INIT_COMPONENT_EXPORT(init_eeprom);
